package com.openlogic.common.logic.decision.scorecard.engine;

import java.math.BigDecimal;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.Deque;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.stream.Collectors;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.StopWatch;
import org.noear.nami.Nami;
import org.noear.solon.Solon;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson2.JSON;
import com.googlecode.aviator.AviatorEvaluator;
import com.openlogic.api.logic.dto.RuleSqlModelDto;
import com.openlogic.api.logic.service.RemoteRuleModelService;
import com.openlogic.common.core.utils.DateUtils;
import com.openlogic.common.logic.cache.DefaultSqlCache;
import com.openlogic.common.logic.constants.RuleConstants;
import com.openlogic.common.logic.constants.RuleTypeConstants;
import com.openlogic.common.logic.decision.common.DecisionEngine;
import com.openlogic.common.logic.decision.common.enums.Logic;
import com.openlogic.common.logic.decision.scorecard.constants.ScoreCardConstants;
import com.openlogic.common.logic.decision.scorecard.model.ScoreCardRow;
import com.openlogic.common.logic.decision.scorecard.model.ScoreCardTable;
import com.openlogic.common.logic.decision.scorecard.model.ScoreCardTableResultVo;
import com.openlogic.common.logic.run.ExecRuleHandler;
import com.openlogic.common.logic.utils.StackExceptionUtils;
import com.openlogic.common.plugins.db.api.utils.DataSourceUtils;
import com.openlogic.common.plugins.spi.enums.DbType;
import com.openlogic.datasource.api.param.ConnectionParam;

import jodd.db.connection.ConnectionProvider;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

/**
* @ClassName: XScoreCardEngine
* @Description: 评分卡执行引擎
* @author weiyongpeng
* @date 2024年9月30日 上午9:11:16
 */
public class XScoreCardEngine extends DecisionEngine{
	
	private static RemoteRuleModelService remoteRuleModelService = Solon.context().getBean(RemoteRuleModelService.class);

	private static final Logger log = LoggerFactory.getLogger(XScoreCardEngine.class);
	
	private static Object[] execLogArray = new Object[2];
	
	private static long DEFAULT_EXPIRE = 5 * 60 * 1000;
    
	private static DefaultSqlCache sqlCache = new DefaultSqlCache(100, DEFAULT_EXPIRE);
    
	private <T> T putCacheValue(String key, T value, long ttl) {
        sqlCache.put(key, value, ttl);
        return value;
    }
	
	private static final String execLogMsg = MessageFormat.format("{0} 正常信息 评分卡:【开始执行】", DateUtils.formatDate(DateUtils.getNowDate(), DateUtils.YYYY_MM_DD_HH_MM_SS));

	static {
		initExecLog(execLogArray,execLogMsg,RuleTypeConstants.decisionTable.getCode());
		if (remoteRuleModelService == null) {
			remoteRuleModelService = Nami.builder().create(RemoteRuleModelService.class);
			Solon.context().beanMake(RemoteRuleModelService.class);
		}
	}
	
	public static Object[] getExecLogArray() {
		return execLogArray;
	}

	/**
	* 描述：评分卡引擎
	* @Title: doDecisionTable
	* @param table
	* @param params
	* @param id
	* @param logs
	* @return
	* @author weiyongpeng
	* @date  2024年9月30日 上午9:33:44
	 */
	public static ScoreCardTableResultVo doDecisionTable(ScoreCardTable table, Map<String, Object> params,
			String id, StringBuilder logs) {
		StopWatch stopWatch = new StopWatch();
		stopWatch.start();
		// 是否加权
		Boolean isWeighting = table.getIsWeighting();
		// 是否加权求和
		Boolean isWeightedSum = isWeighting ? table.getIsWeightedSum() : false;
				
		// 条件参数队列-参数桩
		Deque<Map<Integer, String>> paramValueQueue = new ConcurrentLinkedDeque<>();
		// 条件参数队列-参数桩-中文
		Deque<Map<Integer, String>> paramTextQueue = new ConcurrentLinkedDeque<>();
		// 条件表达式队列-条件桩
		Deque<Map<Integer, String>> conditionValueQueue = new ConcurrentLinkedDeque<>();
		// 条件表达式队列-条件桩-中文
		Deque<Map<Integer, String>> conditionTextQueue = new ConcurrentLinkedDeque<>();
		// 权重队列
		Deque<Map<Integer, Double>> weightValueQueue = new ConcurrentLinkedDeque<>();
		// 分数表达式队列-分数桩
		Deque<Map<Integer, String>> scoreValueQueue = new ConcurrentLinkedDeque<>();
		
		// 评分卡数据信息
		List<List<ScoreCardRow>> scoreCard = table.getScoreCardRows();
		// 开始解析
		JSONArray scorecardArrayJson = JSONArray.fromObject(scoreCard);
		int rowNumSpan = 0;
		for (Object scorecardArr : scorecardArrayJson) {
			JSONArray scoreCardRowArrayJson = JSONArray.fromObject(scorecardArr);
			// 每一行的元素
			for (Object row : scoreCardRowArrayJson) {
				// 行号
				Integer rowNum = (Integer)JSONObject.fromObject(row).get(ScoreCardConstants.ROW_NUM_KEYWORDS);
//				log.info("\n");
//				log.info("rowNum:{} Row:{}", rowNum, row.toString());
				JSONArray scoreCardCellArrayJson = JSONArray.fromObject(JSONObject.fromObject(row).get(ScoreCardConstants.SCORECARD_CELLS_KEYWORDS));
				String cellValue = "";
				String cellText = "";
				for (Object cell : scoreCardCellArrayJson) {
					// 列号
					Integer cellNum = (Integer)JSONObject.fromObject(cell).get(ScoreCardConstants.CELL_NUM_KEYWORDS);
					// 是否跨行
					Integer rowSpan = (Integer)JSONObject.fromObject(cell).get(ScoreCardConstants.ROW_SPAN_KEYWORDS);
					// 单元格类型
					String cellType = (String)JSONObject.fromObject(cell).get(ScoreCardConstants.CELL_TYPE_KEYWORDS);
					// 单元格值
					cellValue = (String)JSONObject.fromObject(cell).get(ScoreCardConstants.CELL_VALUE_KEYWORDS);
					// 单元格中文值
					cellText = (String)JSONObject.fromObject(cell).get(ScoreCardConstants.CELL_TEXT_KEYWORDS);
					// 权重
					Double weight = Optional.ofNullable(JSONObject.fromObject(cell).get(ScoreCardConstants.CELL_WEIGHT_KEYWORDS)).isPresent() ? new BigDecimal(String.valueOf(JSONObject.fromObject(cell).get(ScoreCardConstants.CELL_WEIGHT_KEYWORDS))).divide(new BigDecimal(100D)).doubleValue() : 1.0;
					
					if(cellNum == 1 && cellType.equals(ScoreCardConstants.CellTypeEnums.PARAM_DOT_CELL.getCode()) && rowSpan == 1 && rowNumSpan == 0) {
						Map<Integer, Double> weightValueMap = new HashMap<>();
						weightValueMap.put(rowNum, weight);
						weightValueQueue.push(weightValueMap);
						Map<Integer, String> paramValueMap = new HashMap<>();
						paramValueMap.put(rowNum, cellValue);
						paramValueQueue.push(paramValueMap);
						Map<Integer, String> paramTextMap = new HashMap<>();
						paramTextMap.put(rowNum, cellText);
						paramTextQueue.push(paramTextMap);
					}else if(cellNum == 1 && cellType.equals(ScoreCardConstants.CellTypeEnums.PARAM_DOT_CELL.getCode()) && rowSpan > 1 && weight >= 0) {
						for (int i = 0; i < rowSpan; i++) {
							Map<Integer, Double> weightValueMap = new HashMap<>();
							weightValueMap.put((i+rowNum), weight);
							weightValueQueue.push(weightValueMap);
							Map<Integer, String> paramValueMap = new HashMap<>();
							paramValueMap.put((i+rowNum), cellValue);
							paramValueQueue.push(paramValueMap);
							Map<Integer, String> paramTextMap = new HashMap<>();
							paramTextMap.put((i+rowNum), cellText);
							paramTextQueue.push(paramTextMap);
						}
						rowNumSpan += rowSpan;
					}else if(cellNum == 2 && cellType.equals(ScoreCardConstants.CellTypeEnums.CONDITION_EXPR_CELL.getCode())) {
						Map<Integer, String> conditionValueMap = new HashMap<>();
						generatorConditionExpress(paramValueQueue,rowNum, cellValue,conditionValueMap);
						conditionValueQueue.push(conditionValueMap);
						Map<Integer, String> conditionTextMap = new HashMap<>();
						generatorConditionTextExpress(paramTextQueue,rowNum, cellText,conditionTextMap);
						conditionTextQueue.push(conditionTextMap);
					}else if(cellNum == 3 && cellType.equals(ScoreCardConstants.CellTypeEnums.SCORE_EXPR_CELL.getCode())) {
						Map<Integer, String> scoreValueMap = new HashMap<>();
						if(isWeightedSum) {
							// 取加权后的值
							generatorScoreExpress(weightValueQueue,rowNum, cellValue,scoreValueMap);
						}else {
							scoreValueMap.put(rowNum, cellValue);
						}
						scoreValueQueue.push(scoreValueMap);
					}
//					log.info("\n");
//					log.info("cellNum:{} cell:{}",cellNum, cell.toString());
				}
			}
			rowNumSpan -= 1;
		}
		// 执行评分卡
		ScoreCardTableResultVo resultVo = execuate(conditionValueQueue,conditionTextQueue,scoreValueQueue,table,params,id,logs,stopWatch);
		if(Optional.ofNullable(resultVo.getExecStatus()).isPresent() && resultVo.getExecStatus()) {
			resultVo.setStartTime(DateUtils.formatDate(new Date(stopWatch.getStartTime())));
			Object[] execLogArray = getExecLogArray();
			execLogArray[1] = resultVo;
			resultVo.setExecLog(JSONArray.fromObject(execLogArray).toString());
		}else if(Optional.ofNullable(resultVo.getExecStatus()).isPresent() && !resultVo.getExecStatus()) {
			resultVo.setStartTime(DateUtils.formatDate(new Date(stopWatch.getStartTime())));
			Object[] execLogArray = getExecLogArray();
			execLogArray[1] = resultVo;
			resultVo.setResult(JSONArray.fromObject(execLogArray).toString());
		}else {
			resultVo.setStartTime(DateUtils.formatDate(new Date(stopWatch.getStartTime())));
			Object[] execLogArray = getExecLogArray();
			resultVo.setExecLog("暂无匹配的条件");
			resultVo.setExecStatus(RuleConstants.NODE_EXEC_SUCCESS);
			execLogArray[1] = resultVo;
			resultVo.setExecLog(JSONArray.fromObject(execLogArray).toString());
		}
		return resultVo;
	}

	/**
	* 描述：执行评分卡
	* @Title: execuate
	* @param conditionValueQueue
	* @param conditionTextQueue
	* @param scoreValueQueue 
	* @param table 
	* @param params
	* @param id
	* @param logs
	* @author weiyongpeng
	 * @param stopWatch 
	* @date  2024年9月30日 下午1:03:01
	 */
	private static ScoreCardTableResultVo execuate(Deque<Map<Integer, String>> conditionValueQueue,
			Deque<Map<Integer, String>> conditionTextQueue, Deque<Map<Integer, String>> scoreValueQueue, ScoreCardTable table, Map<String, Object> params, String id, StringBuilder logs, StopWatch stopWatch) {
		ScoreCardTableResultVo resultVo = new ScoreCardTableResultVo();
		resultVo.setId(id);
		logs.append(MessageFormat.format("决策执行id:【{0}】;决策执行开始时间:【{1}】;", id, DateUtils.formatDate(new Date(stopWatch.getStartTime()), DateUtils.YYYY_MM_DD_HH_MM_SS)));
		// 赋值参数
		String assignParamValue = table.getAssignParamValue();
		// 赋值参数-中文
		String assignParamText = table.getAssignParamText();
		Double sum = 0D;
		for (int i =conditionValueQueue.size();i>0;i--) {
			Map<Integer, String> condMap = conditionValueQueue.pollLast();
			Map<Integer, String> condTextMap = conditionTextQueue.pollLast();
			Iterator<Integer> conditionRow = condMap.keySet().iterator();
			while (conditionRow.hasNext()) {
				try {
					Integer conditionKey = conditionRow.next();
					// 2、获取条件表达式 - 这里需要根据变量的类型，执行不同的AviatorExecutor
					String expressValue = doParseExpressValue(condMap.get(conditionKey), params);
					boolean result = (boolean) AviatorEvaluator.execute(expressValue, params, true);
					if (result) {
						Object execute = AviatorEvaluator.execute(scoreValueQueue.pollLast().get(conditionKey), params, true);
						// 将两数转为BigDecimal,保留精度
						String sumStr = String.valueOf(sum);
						String executeStr = String.valueOf(execute);
						BigDecimal executeDecimal = new BigDecimal(executeStr);
						BigDecimal sumDecimal = new BigDecimal(sumStr);
						
						sum = sumDecimal.add(executeDecimal).doubleValue();
						logs.append(MessageFormat.format("决策执行满足{0}:【{1}】 执行结果:【{2}】", conditionKey, condTextMap.get(conditionKey), execute));
//						log.info("执行满足:{} 执行结果:{}",condMap.get(conditionKey), execute);
					}else {
						scoreValueQueue.pollLast();
					}
				} catch (Exception e) {
					log.error("评分卡执行异常:[{}]", e);
					resultVo.setExecStatus(RuleConstants.NODE_EXEC_ERROR);
					resultVo.setResult(MessageFormat.format("决策执行id:【{0}】;评分卡执行异常,异常信息:【{1}】",id, StackExceptionUtils.getExceptionType(e).toString()));
					return resultVo;
				}
			}
		}
		resultVo.setResult(String.join("=",assignParamValue, String.valueOf(sum)));
		resultVo.setExecStatus(RuleConstants.NODE_EXEC_SUCCESS);
		logs.append(MessageFormat.format(";最终计算得分:【{0}】 最终计算结果:【{1}】;", sum, String.join("=",assignParamText, String.valueOf(sum))));
		stopWatch.stop();
		logs.append(MessageFormat.format("决策执行结束时间:【{0}】;决策总耗时:【{1}】毫秒", DateUtils.formatDate(new Date(stopWatch.getStopTime()), DateUtils.YYYY_MM_DD_HH_MM_SS), stopWatch.getTime()));

		resultVo.setExecLog(logs.toString());
//		log.info("最终计算得分:{}", sum);
		return resultVo;
	}

	/**
	* 描述：组装生成条件表达式
	* @Title: generatorConditionExpress
	* @param paramValueQueue 参数队列
	* @param rowNum 行号
	* @param cellValue 条件表达式单元格
	* @param map 条件结果map
	* @author weiyongpeng
	* @date  2024年9月30日 下午2:19:10
	 */
	private static void generatorConditionExpress(Deque<Map<Integer, String>> paramValueQueue,
			Integer rowNum, String cellValue, Map<Integer, String> map) {
		if (cellValue.contains(Logic.AND.toString())) {
			String conditionExpre = String.join(
					StringUtils.SPACE + Logic.AND.toString() + StringUtils.SPACE,
					Arrays.asList(cellValue.split(Logic.AND.toString())).stream().map(i -> String
							.join("",
									paramValueQueue.stream().filter(x -> x.containsKey(rowNum))
											.map(x -> x.get(rowNum)).collect(Collectors.toList()))
							.trim() + i.trim()).collect(Collectors.toList()));
			map.put(rowNum, conditionExpre);
		}else if(cellValue.contains(Logic.OR.toString())) {
			String conditionExpre = String.join(
					StringUtils.SPACE + Logic.OR.toString() + StringUtils.SPACE,
					Arrays.asList(cellValue.split(Logic.OR.toString())).stream().map(i -> String
							.join("",
									paramValueQueue.stream().filter(x -> x.containsKey(rowNum))
											.map(x -> x.get(rowNum)).collect(Collectors.toList()))
							.trim() + i.trim()).collect(Collectors.toList()));
			map.put(rowNum, conditionExpre);
		}
		if(map.isEmpty()) {
			String conditionExpre = String.join(
					StringUtils.SPACE + Logic.AND.toString() + StringUtils.SPACE,
					Arrays.asList(cellValue.split(Logic.AND.toString())).stream().map(i -> String
							.join("",
									paramValueQueue.stream().filter(x -> x.containsKey(rowNum))
											.map(x -> x.get(rowNum)).collect(Collectors.toList()))
							.trim() + i.trim()).collect(Collectors.toList()));
			map.put(rowNum, conditionExpre);
		}
	}
	
	/**
	* 描述：生成中文条件表达式
	* @Title: generatorConditionTextExpress
	* @param paramTextQueue
	* @param rowNum
	* @param cellText
	* @param map
	* @author weiyongpeng
	* @date  2024年10月1日 下午3:53:53
	 */
	private static void generatorConditionTextExpress(Deque<Map<Integer, String>> paramTextQueue, Integer rowNum,
			String cellText, Map<Integer, String> map) {
		if (cellText.contains(Logic.AND.toChnString())) {
			String conditionExpre = String.join(
					StringUtils.SPACE + Logic.AND.toChnString() + StringUtils.SPACE,
					Arrays.asList(cellText.split(Logic.AND.toChnString())).stream().map(i -> String
							.join("",
									paramTextQueue.stream().filter(x -> x.containsKey(rowNum))
											.map(x -> x.get(rowNum)).collect(Collectors.toList()))
							.trim() + i.trim()).collect(Collectors.toList()));
			map.put(rowNum, conditionExpre);
		}else if(cellText.contains(Logic.OR.toChnString())) {
			String conditionExpre = String.join(
					StringUtils.SPACE + Logic.OR.toChnString() + StringUtils.SPACE,
					Arrays.asList(cellText.split(Logic.OR.toChnString())).stream().map(i -> String
							.join("",
									paramTextQueue.stream().filter(x -> x.containsKey(rowNum))
											.map(x -> x.get(rowNum)).collect(Collectors.toList()))
							.trim() + i.trim()).collect(Collectors.toList()));
			map.put(rowNum, conditionExpre);
		}
		if(map.isEmpty()) {
			String conditionExpre = String.join(
					StringUtils.SPACE + Logic.AND.toChnString() + StringUtils.SPACE,
					Arrays.asList(cellText.split(Logic.AND.toChnString())).stream().map(i -> String
							.join("",
									paramTextQueue.stream().filter(x -> x.containsKey(rowNum))
											.map(x -> x.get(rowNum)).collect(Collectors.toList()))
							.trim() + i.trim()).collect(Collectors.toList()));
			map.put(rowNum, conditionExpre);
		}
	}

	
	/**
	 * 描述：组装生成分值表达式
	 * @Title: generatorScoreExpress
	 * @param weightValueQueue 权重队列
	 * @param rowNum 行号
	 * @param cellValue 单元格数值-分数单元格
	 * @param scoreValueMap 分数结果map
	 * @return
	 * @author weiyongpeng
	 * @date  2024年9月30日 上午10:41:34
	 */
	private static void generatorScoreExpress(Deque<Map<Integer, Double>> weightValueQueue, Integer rowNum,
			String cellValue, Map<Integer, String> scoreValueMap) {
		String scoreStr = String.join("", weightValueQueue.stream().filter(x -> x.containsKey(rowNum)).map(
				x -> String.valueOf((new BigDecimal(String.valueOf(x.get(rowNum))).multiply(new BigDecimal(cellValue)))
						.doubleValue()))
				.collect(Collectors.toList()));
		scoreValueMap.put(rowNum, scoreStr);
	}
	
	/**
	* 描述：解析表达式
	* @Title: doParseExpressValue
	* @param value
	* @param param
	* @return
	* @author weiyongpeng
	* @date  2024年12月27日 下午3:15:28
	 */
	@SuppressWarnings("unchecked")
	private static String doParseExpressValue(String value, Map<String, Object> param) {
		String expressValue = value;
		XScoreCardEngine xScoreCardEngine = new XScoreCardEngine();
		// 处理sql参数 @sqlVar2@|10
		JSONObject inputJson = JSONObject.fromObject(param);
		if (expressValue.contains("@") && ExecRuleHandler.extractStrings(expressValue).stream().filter(s -> s.split("\\.").length >= 2).collect(Collectors.toList()).size() > 0) {
			List<String> sqlVarList = ExecRuleHandler.extractStrings(expressValue).stream().filter(s -> s.split("\\.").length >= 2).collect(Collectors.toList());
			Iterator<String> it = inputJson.keys();
			for (String sqlVar : sqlVarList) {
				String[] sqlSplit = sqlVar.split("\\.");
				// 取出需要对比的字段
				String compareVar = sqlSplit[1];
				List<Object> columnValueList = new ArrayList<>();
				while (it.hasNext()) {
					String key = it.next();
					if (sqlSplit[0].equals(key)) {
						List<Map<String,Object>> listObjectFir = (List<Map<String,Object>>) com.alibaba.fastjson.JSONArray.parse((String)sqlCache.get(key));
						if (CollectionUtils.isEmpty(listObjectFir)) {
							listObjectFir = xScoreCardEngine.selectRuleSqlParamRes(inputJson, key, param);
						}
						columnValueList = listObjectFir.stream().filter(mapF -> Optional.ofNullable(mapF.get(compareVar)).isPresent()).map(mapV -> {
							return mapV.get(compareVar);
						}).collect(Collectors.toList());
						param.put(sqlVar.replaceAll("\\.", ""), columnValueList);
					}
				}
				expressValue = expressValue.replaceAll("\\@", "").replaceAll("\\.", "");;
			}
		}else { // 不包含sql参数的字段
			List<String> sqlVarList = ExecRuleHandler.extractStrings(expressValue).stream().collect(Collectors.toList());
			for (String key : sqlVarList) {
				List<Map<String,Object>> listObjectFir = Optional.ofNullable(sqlCache.get(key)).isPresent() ? 
						(List<Map<String,Object>>) com.alibaba.fastjson.JSONArray.parse((String)sqlCache.get(key)) : 
							xScoreCardEngine.selectRuleSqlParamRes(inputJson, key, param);
				param.put(key, listObjectFir);
			}
			expressValue = expressValue.replaceAll("\\@", "");
		}
		return expressValue;
	}
	
	/**
	* 描述：查询sql参数
	* @Title: selectRuleSqlParamRes
	* @param inputjson
	* @param key
	* @param env
	* @return
	* @author weiyongpeng
	* @date  2024年12月27日 下午3:15:03
	 */
	@SuppressWarnings("unchecked")
	private List<Map<String,Object>> selectRuleSqlParamRes(JSONObject inputjson, String key, Map<String, Object> env) {
		String sqlexp;
		// 1、查询sql语句，并执行sql select SQLEXP FROM CONFIG WHERE NAME = ${name}; 所以决策入参正常传递
		RuleSqlModelDto sqlInfoMap = remoteRuleModelService.listRuleModelInner(key).getData();
		String dbType = sqlInfoMap.getDbType();
		ConnectionParam connectionParam = JSON.parseObject(sqlInfoMap.getConnectionParams(), ConnectionParam.class);
		sqlexp = sqlInfoMap.getSqlexp();
		Iterator<String> its = inputjson.keys();
		if(sqlexp.contains("${")) { // 如果有条件参数
			while (its.hasNext()) {
				String key2 = its.next(); 
				if(!key2.equals("everyNodeList") && !key2.equals("areaInfo")) {
					String tmp = "\\$\\{" + key2 + "\\}";
					sqlexp = sqlexp.replaceAll(tmp , "'"+inputjson.getString(key2)+"'");
				}
			}
		}
		// 执行sql获取结果json
		ConnectionProvider connectionProvider = DataSourceUtils.getJdbcTemplate(DbType.getDbType(dbType),
				connectionParam);
		PreparedStatement prepareStatement;
		try {
			prepareStatement = connectionProvider.getConnection().prepareStatement(sqlexp);
			// 2、转化结果集为json 调用字符串的函数 决策设置需要标识出sql参数 加一个#标识 并缓存
			String sqlStr = (String) Optional.ofNullable(sqlCache.get(key)).orElse(
					putCacheValue(key, JSON.toJSONString(prepareStatement.executeQuery(sqlexp)), DEFAULT_EXPIRE));
			env.put(key, sqlStr);
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return (List<Map<String,Object>>) com.alibaba.fastjson.JSONArray.parse((String)sqlCache.get(key));
	}
}
